﻿using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace WenSkin.Forms
{
    [Serializable]
    public class SqlServerConnect
    {
        public SqlServerConnect()
        {
            OpenFilrToConnect();
        }
        public SqlServerConnect(string server, string database, string userid, string password)
        {
            this.Server = server;
            this.DataBase = database;
            this.UserID = userid;
            this.Password = password;
        }
        public string ConStr
        {
            get => string.Format("server={0};database={1};uid={2};pwd={3}", Server, DataBase, UserID, Password);
        }
        public void SaveConnectToFile()
        {
            //string result = Serialize(this);
            string encryptResult = AESEncrypt(ConStr);
            File.WriteAllText(Application.StartupPath + "\\SqlServerConnect.dat", encryptResult);
        }
        public void OpenFilrToConnect()
        {
            string path = Application.StartupPath + "\\SqlServerConnect.dat";
            if (!File.Exists(path))
                return;
            string fileText = File.ReadAllText(path);

            //解密字符串
            string resultStr = AESDecrypt(fileText);

            //SqlServerConnect result = DeSerialize<SqlServerConnect>(resultStr);
            this.Server = Regex.Match(resultStr, @"(?<=server\=).*?(?=;)")?.ToString();
            this.DataBase = Regex.Match(resultStr, @"(?<=database\=).*?(?=;)")?.ToString();
            this.UserID = Regex.Match(resultStr, @"(?<=uid\=).*?(?=;)")?.ToString();
            this.Password = Regex.Match(resultStr, @"(?<=pwd\=).*")?.ToString();
        }
        /// <summary>
        /// 把对象序列化为字符串
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public string Serialize<T>(T entity)
        {
            try
            {
                MemoryStream stream = new MemoryStream();
                BinaryFormatter bf = new BinaryFormatter();
                bf.Serialize(stream, entity);

                byte[] data = stream.ToArray();
                stream.Close();

                return ByteToHexString(data);
            }
            catch
            {
                return "";
            }
        }
        /// <summary>
        /// 将序列化后的字符串反序列化为对象
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public T DeSerialize<T>(string str)
        {
            try
            {
                byte[] data = HexStringToByte(str);
                MemoryStream stream = new MemoryStream();
                stream.Write(data, 0, data.Length);
                stream.Position = 0;

                BinaryFormatter bf = new BinaryFormatter();
                object obj = bf.Deserialize(stream);
                stream.Close();

                return (T)obj;
            }
            catch
            {
                return default(T);
            }
        }

        //将数组转化 成  Hex16进制的字符串格式
        private string ByteToHexString(byte[] data)
        {
            string result = string.Empty;
            foreach (byte b in data)
            {
                result += Convert.ToString(b, 16) + " ";
            }
            result = result.Remove(result.Length - 1);
            return result;
        }
        private byte[] HexStringToByte(string hs)
        {
            //以 空格 分割字符串，并去掉空字符
            string[] chars = hs.Split(' ');
            byte[] b = new byte[chars.Length];
            //逐个字符变为16进制字节数据
            for (int i = 0; i < chars.Length; i++)
            {
                b[i] = Convert.ToByte(chars[i], 16);
            }
            //按照指定编码将字节数组变为字符串
            return b;
        }

        public string Server { get; set; }
        public string DataBase { get; set; }
        public string UserID { get; set; }
        public string Password { get; set; }

        //加密
        public static string AESEncrypt(string data)
        {
            string key = "qw6HjFG2HCZOIl0LXxt4UDofqN0RP5qi";
            string vector = "frhNcbk53xSzKsgf";
            return AESEncrypt(data, key, vector);
        }
        //解密
        public static string AESDecrypt(string data)
        {
            string key = "qw6HjFG2HCZOIl0LXxt4UDofqN0RP5qi";
            string vector = "frhNcbk53xSzKsgf";
            return AESDecrypt(data, key, vector);
        }

        /// <summary>
        /// AES加密
        /// </summary>
        /// <param name="Data">被加密的明文</param>
        /// <param name="Key">密钥</param>
        /// <param name="Vector">向量</param>
        /// <returns>密文</returns>
        public static string AESEncrypt(string Data, string Key, string Vector)
        {
            byte[] plainBytes = Encoding.UTF8.GetBytes(Data);

            byte[] bKey = new byte[32];
            Array.Copy(Encoding.UTF8.GetBytes(Key.PadRight(bKey.Length)), bKey, bKey.Length);
            byte[] bVector = new byte[16];
            Array.Copy(Encoding.UTF8.GetBytes(Vector.PadRight(bVector.Length)), bVector, bVector.Length);

            byte[] Cryptograph = null; // 加密后的密文

            Rijndael Aes = Rijndael.Create();
            try
            {
                // 开辟一块内存流
                using (MemoryStream Memory = new MemoryStream())
                {
                    // 把内存流对象包装成加密流对象
                    using (CryptoStream Encryptor = new CryptoStream(Memory,
                    Aes.CreateEncryptor(bKey, bVector),
                    CryptoStreamMode.Write))
                    {
                        // 明文数据写入加密流
                        Encryptor.Write(plainBytes, 0, plainBytes.Length);
                        Encryptor.FlushFinalBlock();

                        Cryptograph = Memory.ToArray();
                    }
                }
            }
            catch
            {
                Cryptograph = null;
            }

            return Convert.ToBase64String(Cryptograph);
        }

        /// <summary>
        /// AES解密
        /// </summary>
        /// <param name="Data">被解密的密文</param>
        /// <param name="Key">密钥</param>
        /// <param name="Vector">向量</param>
        /// <returns>明文</returns>
        public static string AESDecrypt(string Data, string Key, string Vector)
        {
            byte[] encryptedBytes = Convert.FromBase64String(Data);
            byte[] bKey = new byte[32];
            Array.Copy(Encoding.UTF8.GetBytes(Key.PadRight(bKey.Length)), bKey, bKey.Length);
            byte[] bVector = new byte[16];
            Array.Copy(Encoding.UTF8.GetBytes(Vector.PadRight(bVector.Length)), bVector, bVector.Length);

            byte[] original = null; // 解密后的明文

            Rijndael Aes = Rijndael.Create();
            try
            {
                // 开辟一块内存流，存储密文
                using (MemoryStream Memory = new MemoryStream(encryptedBytes))
                {
                    // 把内存流对象包装成加密流对象
                    using (CryptoStream Decryptor = new CryptoStream(Memory,
                    Aes.CreateDecryptor(bKey, bVector),
                    CryptoStreamMode.Read))
                    {
                        // 明文存储区
                        using (MemoryStream originalMemory = new MemoryStream())
                        {
                            byte[] Buffer = new byte[1024];
                            int readBytes = 0;
                            while ((readBytes = Decryptor.Read(Buffer, 0, Buffer.Length)) > 0)
                            {
                                originalMemory.Write(Buffer, 0, readBytes);
                            }

                            original = originalMemory.ToArray();
                        }
                    }
                }
            }
            catch
            {
                original = null;
            }
            return Encoding.UTF8.GetString(original);
        }
    }
}